import React, { memo, useCallback, useState, forwardRef, useImperativeHandle, useEffect, useRef, useMemo } from 'react';
import { Upload, Modal } from 'antd';
import { InboxOutlined, UploadOutlined } from '@ant-design/icons';
import { PACKAGE_NAME } from './../../app/automatic/package';
import { UploadChangeParam, UploadFile } from 'antd/lib/upload/interface';
import Button from './../button/Button';
import { FileUploadProps, FileUploadRefProps } from './interface';
import message from './../../utils/message/message';
import MIME from './mime';

const { Dragger } = Upload;

const DEFAULT_SIZE = 51200; // 默认50M 单位KB
const DEFAULT_IPFS_URL = '/bk/uploadIpfs/'; // ipfs 上传附件
export const DEFAULT_ACCEPT = '.jpg,.png,.jpeg,.gif,.pdf,.xls,.xlsx,.zip,.rar,.txt,.docx,.pptx,.ppt';
const DEFAULT_MODAL_PROPS = { title: '附件上传', width: 700 };
const DEFAULT_GET_FILE_URL = '/bk/getFile/';

function handleUrl(url: string | undefined) {
  if (!url || url.includes('http') || url.includes(DEFAULT_GET_FILE_URL)) return url;
  return DEFAULT_GET_FILE_URL + url;
}

const FileUpload = (props: FileUploadProps, ref: React.Ref<FileUploadRefProps>) => {

  const isSetDefaultFileList = useRef(false);
  const { accept, maxSize, modalProps, defaultFileList } = props;
  const [fileList, setFileList] = useState<UploadFile[]>([]);

  useImperativeHandle(ref, () => ({
    getFileList: () => fileList.filter(item => item.status === 'done'),
    resetFileList: () => setFileList([])
  }));

  useEffect(() => {
    if (defaultFileList && defaultFileList.length && !isSetDefaultFileList.current) {
      setFileList(defaultFileList);
      isSetDefaultFileList.current = true;
    }
  }, [defaultFileList]);

  const mimeTypes = useMemo(() => {
    const accept = (props.accept || DEFAULT_ACCEPT).split(',');
    return accept.map(item => MIME[item]).flat();
  }, [props.accept]);

  const beforeUpload = useCallback((file) => {
    const _maxSize = maxSize || DEFAULT_SIZE;
    if (_maxSize * 1024 < file.size) return false;

    if (props.only && fileList.length >= 1) {
      message.warning('只能上传一个文件');
      return false;
    }

    if (file.type && !mimeTypes.includes(file.type)) {
      message.warning('格式不支持');
      setFileList(fileList.filter((item: any) => item.uid !== file.uid));
      return false;
    }

    return true;
  }, [maxSize, props.only, fileList, mimeTypes]);

  const _onChange = useCallback((info: UploadChangeParam) => {
    if (info.file.status === 'done') {
      info.fileList.forEach(item => {
        if (item.response) item.url = item.response.filename;
      });
    }

    setFileList(info.fileList.filter(item => item.status));
    props.onChange && props.onChange(info);

    if ((info.file.status === 'done' || info.file.status === 'removed') && props.isBtnMode) {
      props.onOkFiles?.(info.fileList);
    }
  }, [props.onChange, props.isBtnMode, props.onOkFiles]);

  const _onOk = useCallback(() => {
    props.onOkFiles?.(fileList.map(file => file.response));
  }, [fileList, props.onOkFiles]);

  const wrap = useCallback((children: React.ReactElement) => {
    if (!modalProps) return children;
    const handleModalProps = { ...DEFAULT_MODAL_PROPS, ...modalProps, onOk: _onOk };
    return <Modal {...handleModalProps}>{children}</Modal>;
  }, [modalProps, _onOk]);

  const handleFileList = useMemo(() => {
    return fileList.map(item => ({
      ...item,
      url: handleUrl(item.url)
    }));
  }, [fileList]);

  return props.isBtnMode ? (
    <Upload
      onChange={_onChange}
      fileList={handleFileList}
      action={props.action || DEFAULT_IPFS_URL + PACKAGE_NAME + '?m=dev'}
      accept={accept || DEFAULT_ACCEPT}
      beforeUpload={beforeUpload}>
      <Button type='default' icon={<UploadOutlined />}>立即上传</Button>
    </Upload>
  ) : wrap(<Dragger
    {...props}
    beforeUpload={beforeUpload}
    action={props.action || DEFAULT_IPFS_URL + PACKAGE_NAME}
    listType='picture'
    fileList={handleFileList}
    onChange={_onChange}
    accept={accept || DEFAULT_ACCEPT}>
    <p className='ant-upload-drag-icon'><InboxOutlined /></p>
    <p className='ant-upload-text'>选择文件或拖动文件进行上传</p>
    <p className='ant-upload-hint'>
      支持格式：{accept || DEFAULT_ACCEPT}，上传大小限制：{DEFAULT_SIZE || maxSize} KB
    </p>
  </Dragger>);
};

export default memo(forwardRef(FileUpload));